/**
 * Common utility methods for requests, file uploads, etc.
 * @author echo. (Converted to Taro React TS)
 */

import Taro from '@tarojs/taro';
import Utils from "@/utils/common";
import LocalUtils from "@/utils/local_utils";
import {IResponseType} from "@/common/apis/model";
import LocalData from "@/common/local_data";
import RouthPath from "@/common/RouthPath";

class HttpUtils {
  private delayed: NodeJS.Timeout | null;

  // API base URL
  interfaceUrl(): string {
    return LocalData.baseUrl + '/api/yckj';
  }


  /**
   * Request data processing
   * @param url Request address
   * @param method Request method (GET or POST)
   * @param postData Request parameters
   * @param isDelay Whether to delay showing loading
   * @param isForm Data format (true: application/x-www-form-urlencoded, false: application/json)
   * @param hideLoading Whether to hide loading (true: hide, false: show)
   * @param isPullDownRefresh 判断是否刷新
   */
  async request(
    url: string,
    method: 'GET' | 'POST',
    postData?: any,
    isDelay: boolean = false,
    isForm: boolean = false,
    hideLoading: boolean = false,
    isPullDownRefresh: boolean = false, // <--- 新增参数
  ) {
    let loading = false;
    if (this.delayed) {
      await Taro.hideLoading();
      clearTimeout(this.delayed);
      this.delayed = null;
    }
    if (!hideLoading) {
      if (isDelay) {
        this.delayed = setTimeout(() => {
          loading = true;
          Utils.showLoading();
        }, 500);
      } else {
        loading = true;
        Utils.showLoading();
      }
    }
    const fullUrl = Utils.isHttpUrl(url) ? url : this.interfaceUrl() + url;
    const result = await Taro.request({
      url: fullUrl,
      data: postData,
      header: {
        'content-type': isForm ? 'application/x-www-form-urlencoded' : 'application/json',
        'Authorization': LocalUtils.getToken()
      },
      method: method,
      dataType: 'json',
    }).catch((err) => {
      Utils.showErrorToast("网络不给力，请稍后再试~");
    }).finally(() => {
      if (this.delayed) {
        clearTimeout(this.delayed);
        this.delayed = null;
      }
      if (loading && !hideLoading) {
        Taro.hideLoading();
      }
      if (isPullDownRefresh) {
        Utils.stopRefresh()
      }
    });
    if (result && result.data) {
      if (this.isIResponseType(result.data)) {
        if (result.data.code == 0) {
          return result.data.data
        } else if (result.data.code == 10021 || result.data.code == 10020) {
          // 登录失效
          LocalUtils.exitLogin();
          Utils.reLaunch({
            url: RouthPath.login
          }, 1)
        } else {
          Utils.showErrorToast(result.data.msg);
          throw new Error(result.data.msg || '请求失败');
        }
      } else {
        return result.data
      }
    } else {
      Utils.showErrorToast("网络不给力，请稍后再试~");
      throw new Error("网络不给力，请稍后再试~");
    }
  }

  async uploadFile(
    url: string, // 上传的目标接口路径
    filePath: string, // 要上传的文件路径 (必选)
    name: string, // 文件对应的 key (必选，后端接口定义的)
    formData?: any, // 随文件上传的额外参数 (可选)
    isDelay: boolean = false,
    hideLoading: boolean = false
  ) {
    let loading = false;
    if (this.delayed) {
      // 这里和 request 的逻辑一样，如果已有延迟 loading，先清除
      await Taro.hideLoading(); // Taro.hideLoading 是异步的，确保执行完毕
      clearTimeout(this.delayed);
      this.delayed = null;
    }
    if (!hideLoading) {
      if (isDelay) {
        this.delayed = setTimeout(() => {
          loading = true;
          Utils.showLoading('上传中...'); // 可以自定义 loading 文本
        }, 1000);
      } else {
        loading = true;
        Utils.showLoading('上传中...');
      }
    }
    let result = await Taro.uploadFile({
      url: this.interfaceUrl() + url, // 完整的上传 URL
      filePath: filePath,
      name: name,
      formData: formData, // 附带的表单数据
      header: {
        // 'content-type': 'multipart/form-data', // uploadFile 通常会自动设置，但如果后端有特定要求可以加上
        'Authorization': LocalUtils.getToken() // 授权 Token
      },
    }).catch(err => {
      Utils.showErrorToast("网络不给力，请稍后再试~");
    }).finally(() => {
      if (this.delayed) {
        clearTimeout(this.delayed);
        this.delayed = null;
      }
      if (loading && !hideLoading) {
        Taro.hideLoading();
      }
    })
    if (result && result.data) {
      let responseData: any;
      try {
        responseData = JSON.parse(result.data);
      } catch (e) {
        Utils.showErrorToast("服务器响应格式错误~");
        throw new Error("服务器响应格式错误~");
      }
      if (this.isIResponseType(responseData)) {
        if (responseData.code === 0) {
          return responseData.data; // 上传成功，返回 data 字段
        } else {
          Utils.showErrorToast(responseData.msg || '上传失败，请稍后再试');
          throw new Error(responseData.msg || '上传失败');
        }
      } else {
        // 如果响应不是预期的 IResponseType 结构
        Utils.showErrorToast("服务器响应异常~");
        throw new Error("服务器响应异常~");
      }
    } else {
      Utils.showErrorToast("上传失败，请检查网络或联系管理员~");
      throw new Error("上传失败，请检查网络或联系管理员~");
    }
  }

  // Set user information
  setUserInfo(mobile: string, token?: string): void {
    if (token) {
      LocalUtils.setLocalStorage("thorui_token", token);
    }
  }

  isIResponseType(data: any): data is IResponseType {
    return (
      typeof data === 'object' &&
      data !== null &&
      typeof data.code === 'number' &&
      typeof data.msg === 'string' &&
      'data' in data
    );
  }

  // Get token

  // Check if logged in
  isLogin(): boolean {
    return LocalUtils.getLocalStr(LocalData.token);
  }

  // Navigate to page, verify login status
  href(url: string, isVerify: boolean = false): void {
    if (isVerify && !this.isLogin()) {
      Utils.navigateTo({
        url: '/pages/common/login/login'
      });
    } else {
      Utils.navigateTo({
        url: url
      });
    }
  }
}

const httpUtils = new HttpUtils();
export default httpUtils;
